package haust;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;


/**
 * Loads and manages hdml files. <br/>
 * <br/>
 * <br/>
 * HDML Model Format<br/>
 * <br/>
 * .hdml models are stored in binary form<br/> 
 * First 4 bytes is an integer, telling you how many floats follows.<br/> 
 * Next comes a block of float values (4 bytes), these are stored as ( float x, float y, float z )<br/>
 * This repeats 4 times.<br/>
 * <br/>
 * First block is the vertex coordinates<br/>
 * Second block is the texture coordinates<br/>
 * Third block is the normals<br/>
 * Fourth block is indices (Stored as 4 byte integers)<br/>
 * <br/>
 */
public class ModelManager {
	private static String PATHNAME="models/";
	private static ArrayList<ModelContainer> models = new ArrayList<ModelContainer>();

	
	private ModelManager(){
	}

	/**
	 * 
	 * @param a ArrayList to be filled
	 * @param floats a boolean which decides if the read data will be converted to float
	 * @param num number of elements to be read from file
	 * @param file_input 
	 */
	private static void fillArray(ArrayList a, boolean floats, int num, FileInputStream file_input)
	{
		try {
			int buffer = 0;
	        for(int i=0; i<num; ++i){
	      	  buffer = getInt(file_input);
	      	  
	      	  if( floats )
	      		  a.add(Float.intBitsToFloat(buffer));
	      	  else
	      		  a.add(buffer);
	        }
		}
		catch(Exception e) {
			
		}
	}
	
	/**
	 * Loads a .hdml file and stores it in the ArrayList
	 * it will automatically check in the "models/" folder 
	 * example: "file.hdml" will become "models/file.hdml" before attempting to load the model.s
	 * 
	 * @param fileName
	 */
	public static void addModel(String fileName)
	{
		ArrayList<Float> cords = new ArrayList<Float>();
		ArrayList<Float> normals = new ArrayList<Float>();
		ArrayList<Float> texCords = new ArrayList<Float>();
		ArrayList<Integer> indices = new ArrayList<Integer>();
		FileInputStream file_input;
	
		try{
			//number of floats in the parsed document
			file_input = new FileInputStream (PATHNAME+fileName);
		
			//getInt() returns and integer, and fillArray reads that many floats from the file.
		    fillArray(cords, true, getInt(file_input), file_input );
		    fillArray(texCords, true, getInt(file_input), file_input );
		    fillArray(normals, true, getInt(file_input), file_input );
		    fillArray(indices, false, getInt(file_input), file_input );
		
		    file_input.close();
		}catch(Exception e){
		    System.out.println("There was an issue reading from the file: " + e);
		    System.exit(0);
		}
		
		models.add(new ModelContainer(fileName, cords,texCords, normals,indices ));
	}
	
	
	/**
	 * Creates a new SceneObject is modelName is found in the ArrayList<ModelContainer>
	 * 
	 * @param modelName
	 * @return SceneObject with the modeldata or null if model is not found
	 */
	public static SceneObject createNewObject(String modelName){
		for(int i=0; i<models.size();i++){
			if(modelName.equalsIgnoreCase(models.get(i).getModelName())){
				return new SceneObject( models.get(i) );
			}
		}
		
		return null;		
	}
	
	/**
	 * clears the model arraylist
	 */
	public static void destroy()
	{
		models.clear();
	}
	
	
	/**
	 * Reads 4 bytes from the file
	 * @param file_input
	 * @return an int value representing 4 bytes from the file
	 */
	private static int getInt(FileInputStream file_input){ 
		int num = 0;
		try {
			num = (file_input.read());
			num |= (file_input.read() << 8);
			num |= (file_input.read() << 16);
			num |= (file_input.read() << 24);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	     
		return num; 
	}
}
